package com.niiwoo.civet.trade.service.local.notify.impl;

import com.niiwoo.civet.trade.dao.entity.Project;
import com.niiwoo.civet.trade.dao.entity.ProjectBorrowerPlan;
import com.niiwoo.civet.trade.dao.entity.ProjectBorrowerSummary;
import com.niiwoo.civet.trade.dao.mapper.ProjectBorrowerPlanNewMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectMapperExt;
import com.niiwoo.civet.trade.dto.BorrowerRepaymentAmount;
import com.niiwoo.civet.trade.dto.ProjectBorrowerPlanNewDTO;
import com.niiwoo.civet.trade.enums.NotifyTypeEnum;
import com.niiwoo.civet.trade.service.local.notify.AbstractNotifier;
import com.niiwoo.civet.user.dto.request.AppButtonDTO;
import com.niiwoo.civet.user.dto.request.JPushExtDTO;
import com.niiwoo.civet.user.dto.request.UserLetterRequestDTO;
import com.niiwoo.civet.user.enums.*;
import com.niiwoo.tripod.provider.exception.BizException;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

@Slf4j
@Component
public class ProjectRepaymentRemindNotifier extends AbstractNotifier<ProjectBorrowerSummary> {

    @Autowired
    ProjectMapperExt projectMapperExt;
    
    @Autowired
    private ProjectBorrowerPlanNewMapperExt projectBorrowerPlanNewMapper;
    
    @Value("${h5-borrow-detail-url}")
    private String h5BorrowDetailUrl;
    
    @Override
    protected List<? extends UserNotifyInfo> getUserNotifyInfoList(ProjectBorrowerSummary t) {
        RepaymentRemindNotifyInfo info = new RepaymentRemindNotifyInfo();
        info.setBorrowerUserId(t.getBorrowerUserId());
        info.setProjectId(t.getProjectId());
        info.setProjectTitle(t.getProjectTitle());
        info.setCurrentPeriod(t.getCurrentPeriod());
        info.setTotalPeriod(t.getTotalPeriod());
        info.setPeriodString(t.getCurrentPeriod()+"/" + t.getTotalPeriod());
        info.setRefundDate(t.getRefundDate());
        info.setRefundDateString(FastDateFormat.getInstance("MM月dd日").format(t.getRefundDate()));
        info.setRemainShouldRefundedAmount(this.getBorrowerRepaymentAmount(t.getProjectId(),t.getCurrentPeriod()).getRemainShouldRefundedAmount());
        return Collections.singletonList(info);
    }

    @Override
    protected SMSRequest getSMSRequestDTO(UserNotifyInfo info) {
        //短信还款前7天，前3天提醒
        RepaymentRemindNotifyInfo remindNotifyInfo = (RepaymentRemindNotifyInfo)info;

        SMSRequest smsRequest = new SMSRequest();
        smsRequest.setUserId(remindNotifyInfo.getBorrowerUserId());

        // 转换短信模板
        Project project = projectMapperExt.selectByPrimaryKey(remindNotifyInfo.getProjectId());
        Optional<SMSTemplateKeyEnum> smsTemplateKeyEnum = Optional.empty();
        try {
            smsTemplateKeyEnum = SMSTemplateExtend.get(project.getType(), project.getFromSource(), SMSTemplateKeyEnum.BORROW_REPAYMENT_REMIND);
        }catch (Exception e){
            if (e instanceof NoSuchElementException){
                log.info("smsTemplateKeyEnum not exists,use default template ,projectType={},fromSource={},projectId={}",project.getType(),project.getFromSource(),project.getProjectId());
                smsTemplateKeyEnum = Optional.of(SMSTemplateKeyEnum.BORROW_REPAYMENT_REMIND);
            }else {
                log.error("smsTemplateKeyEnum not exists ,projectId={}",project.getProjectId());
            }
        }
        smsRequest.setSmsTemplateKeyEnum(smsTemplateKeyEnum.orElse(SMSTemplateKeyEnum.BORROW_REPAYMENT_REMIND));
        List<Object> paramList = Arrays.asList(remindNotifyInfo.getProjectTitle(), ((RepaymentRemindNotifyInfo) info).getPeriodString(), remindNotifyInfo.getRemainShouldRefundedAmount(),remindNotifyInfo.getRefundDateString());
        smsRequest.setParamList(paramList);
        return smsRequest;
    }

    @Override
    protected UserLetterRequestDTO getUserLetterRequestDTO(UserNotifyInfo info) {
        RepaymentRemindNotifyInfo p = (RepaymentRemindNotifyInfo) info;

        String borrowerUserId = p.getBorrowerUserId();
        Long projectId = p.getProjectId();
        String projectTitle = p.projectTitle;
        BigDecimal remainShouldRefundedAmount = p.getRemainShouldRefundedAmount();
        String periodString = p.getPeriodString();
        String refundDateString = p.getRefundDateString();

        UserLetterRequestDTO letterRequest = new UserLetterRequestDTO();

        //发站内信
        AppButtonDTO rechargeButton = new AppButtonDTO();
        rechargeButton.setLabel("充值");
        rechargeButton.setButtonType(AppButtonDTO.ButtonTypeEnum.RECHARGE);

        AppButtonDTO loanButton = new AppButtonDTO();
        loanButton.setLabel("借款详情");
        loanButton.setButtonType(AppButtonDTO.ButtonTypeEnum.MONMY_LOAN_DETAILEY_2);
        Map<String, Object> loanButtonParam = new HashMap<>();
        loanButtonParam.put("ProjectId", projectId);
        loanButtonParam.put("LoadServerUrl", h5BorrowDetailUrl+projectId);
        loanButton.setParams(loanButtonParam);

        List<AppButtonDTO> listForButton = new ArrayList<>();
        listForButton.add(rechargeButton);
        listForButton.add(loanButton);

        letterRequest.setLetterButtonList(listForButton);

        List<Object> letterTemplateParamList =  Arrays.asList(projectId, projectTitle, periodString, remainShouldRefundedAmount,refundDateString);
        List<Object> jPushTemplateParamList =  Arrays.asList(projectTitle, periodString, remainShouldRefundedAmount,refundDateString);
        letterRequest.setLetterTemplateEnum(MessageTemplateKeyEnum.LetterTemplateKeyEnum.BORROW_REPAYMENT_REMIND);
        letterRequest.setLetterTemplateParamList(letterTemplateParamList);
        letterRequest.setJpushTemplateKeyEnum(MessageTemplateKeyEnum.JPushTemplateKeyEnum.BORROW_REPAYMENT_REMIND);
        letterRequest.setJpushTemplateParamList(jPushTemplateParamList);
        letterRequest.setToUserId(borrowerUserId);
        letterRequest.setProjectId(projectId);
        letterRequest.setUserLetterTypeEnum(UserLetterTypeEnum.LETTER_AND_JPUSH);
        JPushExtDTO jPushExtDTO = new JPushExtDTO();
        jPushExtDTO.setRedirectPageEnum(JPushEnum.RedirectPageEnum.NOTICE_LIST_PAGE);
        letterRequest.setJPushExt(jPushExtDTO);

        return letterRequest;
    }

    private BorrowerRepaymentAmount getBorrowerRepaymentAmount(Long projeectId, int currentPeriod){
		ProjectBorrowerPlanNewDTO projectBorrowerPlanNewDTO = Optional.ofNullable(projectBorrowerPlanNewMapper.selectByProjectIdAndPeroidForAmount(projeectId, currentPeriod))
				.orElseThrow(() -> new BizException("TRD20009"));
		
        ////已还金额
		BigDecimal alreadyRefundedAmount = projectBorrowerPlanNewDTO.getRefundedCapital()
				.add(projectBorrowerPlanNewDTO.getRefundedInterest())
				.add(projectBorrowerPlanNewDTO.getRefundedPenaltyFee())
				.add(projectBorrowerPlanNewDTO.getRefundedGuaranteeFee())
				.add(projectBorrowerPlanNewDTO.getRefundedManagementFee());

        //应还金额
        BigDecimal shouldRefundedAmount = projectBorrowerPlanNewDTO.getCapital()
                .add(projectBorrowerPlanNewDTO.getInterest())
                .add(projectBorrowerPlanNewDTO.getPenaltyFee())
                .add(projectBorrowerPlanNewDTO.getManagementFee())
                .add(projectBorrowerPlanNewDTO.getGuaranteeFee());

        //剩余应还金额
        BigDecimal remainShouldRefundedAmount = shouldRefundedAmount.subtract(alreadyRefundedAmount);

        return new BorrowerRepaymentAmount(alreadyRefundedAmount,shouldRefundedAmount,remainShouldRefundedAmount);
    }

    @Getter
    @Setter
    protected static class RepaymentRemindNotifyInfo extends UserNotifyInfo {

        private String borrowerUserId;

        private Long projectId;

        private String projectTitle;

        private BigDecimal remainShouldRefundedAmount; //剩余应还金额

        private Date refundDate;

        private String refundDateString;

        private Integer currentPeriod;

        private Integer totalPeriod;

        private String periodString;
    }

    @Override
    protected NotifyTypeEnum getType() {
        return NotifyTypeEnum.JS016;
    }
}
